//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>

extern void DzYield();

#define THREADAMOUNT        100
#define RECYCLE             100

uint_t      uAccount;
IThread     *g_pISuspendThread[THREADAMOUNT];

Int32 SuspendThreadTest01(void *pvPara)
{
    IThread         *pIThread;
    ThreadState     thdState;
    ECode     ec;

    ec = DzGetCurrentThread(&pIThread);
    if (FAILED(ec)) {
        kprintf("GetCurrentThread failed, the ec = 0x%08x\n", ec);

        return ec;
    }

    ec = pIThread->Suspend();
    assert(NOERROR == ec);

    ec = pIThread->GetState(&thdState);
    assert(NOERROR == ec);
    assert(ThreadState_Running == thdState);

    pIThread->Release();

    return ec;
}

Int32 InterruptSuspendThread01(void *pvPara)
{
    while (1) {
        if (NULL != g_pISuspendThread[uAccount]) {
            g_pISuspendThread[uAccount]->Interrupt();
        }

        DzYield();
    }

    return NOERROR;
}

EXTERN void SuspendResumeThread1()
{
    ThreadState     thdState;
    ECode         ec;
    uint_t          j;

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        ec = DzCreateKernelThread(SuspendThreadTest01, (void *)0, 0,
                        (ThreadPriorityRank)0xFFFFEEEE, &g_pISuspendThread[uAccount]);

        if (FAILED(ec)) {
            kprintf("Create thread %d failed, the ec = 0x%08x\n", uAccount, ec);

            return;
        }
    }

    ec = DzCreateKernelThread(InterruptSuspendThread01, (void *)0, 0,
                                (ThreadPriorityRank)0xFFFFEEEE, NULL);

    if (FAILED(ec)) {
        kprintf("Create thread failed, the ec = 0x%08x\n", ec);

        return;
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        for (j = 0; j < RECYCLE - 1; j++) {
            ec = g_pISuspendThread[uAccount]->Suspend();
            assert(NOERROR == ec);
            DzYield();
        }
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        ec = g_pISuspendThread[uAccount]->GetState(&thdState);
        assert(NOERROR == ec);
        assert(ThreadState_Suspended == thdState);
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        for (j = 0; j < RECYCLE; j++) {
            ec = g_pISuspendThread[uAccount]->Resume();
            assert(NOERROR == ec);
            DzYield();
        }
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        ec = g_pISuspendThread[uAccount]->GetState(&thdState);
        assert(NOERROR == ec);
        assert(ThreadState_Suspended != thdState);
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        ec = g_pISuspendThread[uAccount]->Join(INFINITE);
        assert(NOERROR == ec);
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        ec = g_pISuspendThread[uAccount]->Join(INFINITE);
        assert(NOERROR == ec);
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        for (j = 0; j < RECYCLE; j++) {
            ec = g_pISuspendThread[uAccount]->Suspend();
            assert(E_FAIL == ec);
        }
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        ec = g_pISuspendThread[uAccount]->GetState(&thdState);
        assert(NOERROR == ec);
        assert(ThreadState_Suspended != thdState);
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        for (j = 0; j < RECYCLE; j++) {
            ec = g_pISuspendThread[uAccount]->Resume();
            assert(E_FAIL == ec);
        }
    }

    for (uAccount = 0; uAccount < THREADAMOUNT; uAccount++) {
        g_pISuspendThread[uAccount]->Release();
        g_pISuspendThread[uAccount] = NULL;
    }
}

Int32 SuspendThreadMutex01(void *pvPara)
{
    IThread         *pIThread;
    ThreadState     thdState;
    ECode         ec;

    DzSleep(100);

    ec = DzGetCurrentThread(&pIThread);
    assert(NOERROR == ec);

    ec = pIThread->GetState(&thdState);
    assert(NOERROR == ec);
    assert(ThreadState_Running == thdState);

    ec = pIThread->GetState(&thdState);
    assert(NOERROR == ec);
    assert(ThreadState_Running == thdState);

    DzYield();

    ec = pIThread->GetState(&thdState);
    assert(NOERROR == ec);
    assert(ThreadState_Running == thdState);

    pIThread->Release();

    return ec;
}

EXTERN void SuspendResumeThread0()
{
    IThread     *pIThread[THREADAMOUNT];
    ECode     ec;
    uint_t      i;
    uint_t      j;

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = DzCreateKernelThread(SuspendThreadMutex01, (void *)i, 0,
                                    (ThreadPriorityRank)0xFFFFEEEE, &pIThread[i]);

        if (FAILED(ec)) {
            kprintf("Create thread %d failed, the ec = 0x%08x\n", i, ec);

            return;
        }

        for (j = 0; j < RECYCLE; j++) {
            ec = pIThread[i]->Suspend();
            assert(NOERROR == ec);
        }
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        for (j = 0; j < RECYCLE; j++) {
            ec = pIThread[i]->Resume();
            assert(NOERROR == ec);
        }
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = pIThread[i]->Join(INFINITE);
        assert(NOERROR == ec);
        pIThread[i]->Release();
    }
}
